package com.springboot.test.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.springboot.test.common.enums.ErrorCode;
import com.springboot.test.common.enums.GoodsStatus;
import com.springboot.test.common.enums.MessageTypeEnum;
import com.springboot.test.common.exception.BizException;
import com.springboot.test.common.utils.ConvertUtils;
import com.springboot.test.entity.GoodsEntity;
import com.springboot.test.entity.TradeRecordEntity;
import com.springboot.test.entity.UserEntity;
import com.springboot.test.entity.mapper.TradeRecordMapper;
import com.springboot.test.service.param.pageparam.BasePageParam;
import com.springboot.test.service.result.GoodsPageResult;
import com.springboot.test.service.result.TradeRecordResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class TradeRecordService extends ServiceImpl<TradeRecordMapper, TradeRecordEntity> {

    @Resource
    private GoodsService goodsService;

    @Resource
    private MessageService messageService;

    @Resource
    private UserService userService;

    @Transactional
    public synchronized Boolean pay(String userCode, String goodsCode) {
        GoodsEntity goodsEntity = goodsService.queryOneByCode(goodsCode);
        if(goodsEntity!=null){
            goodsEntity.setStatus(GoodsStatus.WAIT_TRADE.getCode());
            TradeRecordEntity tradeRecordEntity = new TradeRecordEntity();
            tradeRecordEntity.setTradePrice(goodsEntity.getPrice());
            tradeRecordEntity.setUserCode(userCode);
            tradeRecordEntity.setGoodsCode(goodsCode);
            tradeRecordEntity.setTradeStatus(0);
            UserEntity userEntity = userService.queryOneByCode(userCode);
            messageService.sendMessage(goodsEntity.getPublishUserCode(),goodsCode, MessageTypeEnum.PAY.getCode(), goodsEntity.getGoodsName(),userEntity.getPhone());
            messageService.sendMessage(userCode,goodsCode, MessageTypeEnum.PAY_DONE.getCode(), goodsEntity.getGoodsName(),null);
            goodsService.updateById(goodsEntity);
            save(tradeRecordEntity);
            return Boolean.TRUE;
        }
        throw new BizException(ErrorCode.ERROR);
    }

    public Boolean confirmTrade(String userCode, String goodsCode) {
        GoodsEntity goodsEntity = goodsService.queryOneByCode(goodsCode);
        goodsService.updateStatus(goodsCode,GoodsStatus.TRADE.getCode());
        TradeRecordEntity tradeRecordEntity = getOne(new QueryWrapper<TradeRecordEntity>().lambda().eq(TradeRecordEntity::getUserCode,userCode).eq(TradeRecordEntity::getGoodsCode,goodsCode).eq(TradeRecordEntity::getTradeStatus,0));
        if(tradeRecordEntity==null){
            throw new BizException(ErrorCode.ERROR);
        }
        tradeRecordEntity.setTradeStatus(2);
        messageService.sendMessage(userCode,goodsCode,MessageTypeEnum.TRADE_DONE.getCode(),goodsEntity.getGoodsName(),null);
        updateById(tradeRecordEntity);
        return Boolean.TRUE;
    }

    public Page<TradeRecordResult> pageResult(String userCode, BasePageParam param) {
        Page<TradeRecordEntity> page = page(new Page<>(param.getPageNum(),param.getPageSize())
                ,new QueryWrapper<TradeRecordEntity>().lambda().eq(TradeRecordEntity::getUserCode,userCode).orderByDesc(TradeRecordEntity::getCreateTime));
        List<TradeRecordEntity> records = page.getRecords();
        if(CollectionUtils.isEmpty(records)){
            return new Page<>(param.getPageNum(),param.getPageSize());
        }
        List<String> goodsCodes = records.stream().map(TradeRecordEntity::getGoodsCode).collect(Collectors.toList());
        List<GoodsPageResult> resultList = goodsService.listByGoodsCodes(goodsCodes);
        Map<String, GoodsPageResult> goodsMap = resultList.stream().collect(Collectors.toMap(GoodsPageResult::getGoodsCode, a -> a));
        List<TradeRecordResult> recordResults = new ArrayList<>();
        for (TradeRecordEntity record : records) {
            TradeRecordResult result = ConvertUtils.convert(record,TradeRecordResult.class);
            GoodsPageResult goodsPageResult = goodsMap.get(result.getGoodsCode());
            result.setGoodsName(goodsPageResult.getGoodsName());
            result.setIndexImg(goodsPageResult.getIndexImg());
            result.setStatus(record.getTradeStatus());
            if(result.getStatus()==0){
                result.setStatusInfo("已支付");
            }else if (result.getStatus()==1){
                result.setStatusInfo("已退款");
            }else {
                result.setStatusInfo("已完成");
            }
            recordResults.add(result);
        }
        Page<TradeRecordResult> resultPage = new Page<>(param.getPageNum(),param.getPageSize());
        resultPage.setTotal(page.getTotal());
        resultPage.setRecords(recordResults);
        return resultPage;
    }
    @Transactional
    public Boolean cancelTrade(String userCode,String goodsCode) {
        GoodsEntity goodsEntity = goodsService.queryOneByCode(goodsCode);
        goodsEntity.setStatus(1);
        messageService.sendMessage(goodsEntity.getPublishUserCode(),goodsCode,MessageTypeEnum.USER_PAY_BACK.getCode(),goodsEntity.getGoodsName(),null);
        messageService.sendMessage(userCode,goodsCode,MessageTypeEnum.PAY_BACK.getCode(), goodsEntity.getGoodsName(),null);
        TradeRecordEntity tradeRecordEntity = getOne(new QueryWrapper<TradeRecordEntity>().lambda().eq(TradeRecordEntity::getUserCode,userCode).eq(TradeRecordEntity::getGoodsCode,goodsCode).eq(TradeRecordEntity::getTradeStatus,0));
        if(tradeRecordEntity==null){
            throw new BizException(ErrorCode.ERROR);
        }
        tradeRecordEntity.setTradeStatus(1);
        updateById(tradeRecordEntity);
        goodsService.updateById(goodsEntity);
        return Boolean.TRUE;
    }
}
